class Stack {
	volatile int[] stackArray;
	volatile int top;
	volatile int maxSize;

	public Stack(int size) {
		this.maxSize = size;
		stackArray = new int[maxSize];
		top = -1;
	}

	public synchronized boolean isEmpty() {
		return (top == -1);
	}

	public synchronized boolean isFull() {
		return (top == maxSize - 1);
	}

	public synchronized void push(int a) {
		while (isFull()) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		stackArray[++top] = a;
		System.out.println("Pushed :" + a);
		notifyAll();
	}

	public synchronized int pop() {
		int pop = 0;
		while (isEmpty()) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		pop = stackArray[top--];
		notifyAll();
		return pop;
	}
}

class ThreadA implements Runnable {
	String tname = null;
	Stack st = null;

	public ThreadA(Stack st, String tname) {
		this.st = st;
		this.tname = tname;
	}

	public void run() {
		System.out.println("Inside A");
		for (int i = 1; i <= 20; i++) {
			try {
				st.push(i);
			} catch (Exception e) {
			}
		}
	}
}

class ThreadB extends Thread {
	String tname = null;
	Stack st = null;

	public ThreadB(Stack st, String tname) {
		this.st = st;
		this.tname = tname;
	}

	public void run() {
		while (true) {
			try {
				int y = st.pop();
				System.out.println(y + " Is poped");
			} catch (Exception e) {
			}
		}
	}
}

class TestStackThread {
	public static void main(String as[]) {
		Stack st = new Stack(5);
		ThreadA t1 = new ThreadA(st, "A");
		ThreadB t2 = new ThreadB(st, "B");
		Thread tt1 = new Thread(t1);
		Thread tt2 = new Thread(t2);
		tt1.start();
		tt2.start();
	}
}